<template>
   <div class="chart">
    <h3>
      <span class="title-text" :title="`${$t(title)}${$t('message.lineChart')}`">{{ $t(title) }}{{ $t("message.lineChart") }}</span>
      <!-- 最大值显示组件 -->
      <div v-if="isZoomed && currentMaxValue !== null" class="max-value-display">
        <span class="max-label">最大值:</span>
        <span class="max-value">{{ currentMaxValue.toFixed(2) }}</span>
        <!-- <span class="max-unit">{{ unit }}</span> -->
      </div>
      <div class="icon-container">
        <el-icon v-if="!isZoomed" size="22px" @click="handleZoom"><FullScreen /></el-icon>
        <el-icon v-else size="22px" @click="handleZoom"><CloseBold /></el-icon>
      </div>
    </h3>
    <div class="chart-item" ref="chartRef"></div>
    <span class="border_bg_leftTop"></span>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'
import { FullScreen, CloseBold } from '@element-plus/icons-vue'

const props = defineProps({
  deviceId: {
    type: Number,
    required: true
  },
  title: {
    type: String,
    required: true
  },
  color: {
    type: String,
    required: true
  },
  data: {
    type: Array,
    required: true
  },
  xAxisData: {
    type: Array,
    required: true
  },
  unit: {
    type: String,
    default: ''
  },
  zoomId: {
    type: Number,
    required: true
  },
  isZoomed: {
    type: Boolean,
    default: false
  },
  legendName: {
    type: String,
    required: true
  }
})

const emit = defineEmits(['zoom'])

const chartRef = ref<HTMLElement>()
const chart = ref<echarts.ECharts | null>(null)
const currentMaxValue = ref<number | null>(null)

let resizeObserver: ResizeObserver | null = null

// 量程动态调整相关
const threshold = 1 // 降低阈值使量程更敏感
const isUV = props.legendName === '紫外'

// 每条曲线独立的最大/最小值和量程
const chartRange = ref<{ min: number, max: number }>({ min: 0, max: 100 })
const lastRange = ref<{ min: number, max: number }>({ min: 0, max: 100 })

// 性能优化：缓存静态配置
let baseOption: any = null
let isInitialized = false

// 逐帧渲染相关变量
let frameRequestId: number | null = null
let pendingUpdate = false
let lastFrameTime = 0
const FRAME_INTERVAL = 8 // 约120fps，配合逐点渲染

// 处理窗口大小变化的函数
const handleChartResize = () => {
  if (chart.value) {
      //@ts-ignore
      chart.value.resize()
      // 窗口大小变化时重新更新图表，以便重新计算标签显示
      updateChart()
  }
}

// 初始化基础配置（只执行一次）
const initBaseOption = () => {
  if (baseOption) return
  
  baseOption = {
    legend: { show: true, textStyle: { color: '#fff' }, right: '0%', top: '1' },
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(255, 255, 255, 0.9)',
      borderColor: '#1890ff',
      borderWidth: 1,
      textStyle: {
        color: '#333'
      },
      axisPointer: {
        type: 'cross',
        snap: true, // 确保tooltip吸附到最近的数据点
        label: {
          backgroundColor: '#6a7985'
        },
        lineStyle: {
          color: '#ff4d4f',
          width: 1,
          type: 'solid'
        }
      },
      formatter: (params: any[]) => {
        const param = params[0];
        let time = param.name;
        const value = param.value;
        const seriesName = param.seriesName;
        
        // 格式化时间显示，与x轴保持一致
        const date = new Date(time);
        if (!isNaN(date.getTime())) {
          const hours = date.getHours().toString().padStart(2, '0');
          const minutes = date.getMinutes().toString().padStart(2, '0');
          const seconds = date.getSeconds().toString().padStart(2, '0');
          time = `${hours}:${minutes}:${seconds}`;
        }
        
        return `
          时间：${time}<br/>
          ${seriesName}：<b>${value}</b>
        `;
      }
    },
    grid: { left: '20', right: '20', bottom: '10', containLabel: true, top: 10 },
    xAxis: {
      type: 'category',
      nameLocation: 'end',
      nameGap: 10,
      nameTextStyle: { color: '#fff', fontSize: 14, padding: [10, 0, 0, 0] },
      data: [],
      axisLabel: { 
        show: true, 
        color: '#fff',
        formatter: function (value: string) {
          const date = new Date(value);
          if (isNaN(date.getTime())) {
            return value;
          }
          const hours = date.getHours().toString().padStart(2, '0');
          const minutes = date.getMinutes().toString().padStart(2, '0');
          const seconds = date.getSeconds().toString().padStart(2, '0');
          return `${hours}:${minutes}:${seconds}`;
        }
      },
      splitLine: { show: true, lineStyle: { color: 'rgba(255,255,255,0.1)', type: 'dashed' } },
      axisLine: { show: true, lineStyle: { color: '#fff', width: 2 } },
      axisTick: { show: false }
    },
    yAxis: {
      type: 'value',
      nameTextStyle: { color: '#fff', fontSize: 14, padding: [0, 0, 0, 0] },
      min: 0,
      max: 100,
      minInterval: 1,
      axisLabel: { 
        show: true, 
        formatter: function(value: number) {
          return Math.round(value).toString(); // 确保显示整数
        }, 
        color: '#fff' 
      },
      splitLine: { show: true, lineStyle: { color: 'rgba(255,255,255,0.1)', type: 'dashed' } },
      axisLine: { show: true, lineStyle: { color: '#fff', width: 2 } },
      axisTick: { show: false },
      splitArea: { show: false }
    },
    series: []
  }
}
// 使用循环替代扩展运算符
function findMinMax(values: number[]):{min: number, max: number} {
  if (values.length === 0) return { min: 0, max: 100 }
  
  let min = values[0]
  let max = values[0]
  
  for (let i = 1; i < values.length; i++) {
    if (values[i] < min) min = values[i]
    if (values[i] > max) max = values[i]
  }
  
  return { min, max }
}
// 逐帧渲染优化函数
const scheduleFrameUpdate = () => {
  if (pendingUpdate) return;
  
  pendingUpdate = true;
  
  if (frameRequestId) {
    cancelAnimationFrame(frameRequestId);
  }
  
  frameRequestId = requestAnimationFrame((currentTime) => {
    // 帧率控制：确保不超过60fps
    if (currentTime - lastFrameTime < FRAME_INTERVAL) {
      scheduleFrameUpdate();
      return;
    }
    
    lastFrameTime = currentTime;
    pendingUpdate = false;
    performChartUpdate();
  });
};

// 高频更新优化：减少不必要的重绘
let lastUpdateTime = 0
const MIN_UPDATE_INTERVAL = 10 // 最小更新间隔（毫秒）

// 实际执行图表更新的函数
const performChartUpdate = () => {
  if (!chartRef.value) {
    console.error('chartRef.value is null for:', props.legendName);
    return;
  }

  if (!chart.value) {
    chart.value = echarts.init(chartRef.value);
  }

  // 初始化基础配置
  if (!isInitialized) {
    initBaseOption()
    chart.value.setOption(baseOption, { notMerge: true, silent: true });
    isInitialized = true
  }

  let dataValues: number[][] = []
  if (Array.isArray(props.data) && Array.isArray(props.data[0])) {
    dataValues = props.data as number[][]
  } else if (Array.isArray(props.data)) {
    dataValues = [props.data as number[]]
  }
  const xAxisValues: string[] = Array.isArray(props.xAxisData) ? (props.xAxisData as string[]) : []
  const allValues = dataValues.flat()
    // 更新最大值显示（仅在放大模式下）
  if (props.isZoomed && allValues.length > 0) {
    const { max } = findMinMax(allValues)
    currentMaxValue.value = max
  } else {
    currentMaxValue.value = null
  }

  // 紫外曲线优化逻辑 - 在放大模式下使用高效算法
  if (isUV) {
    let minY = 0, maxY = 100
    if (allValues.length > 0) {
      // 放大模式下使用优化的量程计算
      if (props.isZoomed && allValues.length > 50) {
        const { min, max } = findMinMax(allValues)
        minY = min
        maxY = max
      } else {
        // 正常模式使用原有逻辑
        const range = findMinMax(allValues);
        minY = range.min;
        maxY = range.max;
      }
      if (maxY > 10000) {
        minY = 0
        maxY += maxY
      } else if (maxY > 1000) {
        minY = 0
        maxY += Math.floor(maxY/3)
      } else {
        minY -= 400
        maxY += 400
      }
    }
    chartRange.value = { min: minY, max: maxY }
    lastRange.value = { min: minY, max: maxY }
  } else {
    // 非紫外曲线动态量程 - 确保曲线在中间显示
    if (allValues.length > 0) {
      let result = findMinMax(allValues)
      
      // 根据传感器类型设置最小显示范围
      let minDisplayRange = 10 // 默认最小范围
      if (props.legendName.includes('温度')) {
        minDisplayRange = 8 // 温度：最小8度范围
      } else if (props.legendName.includes('湿度')) {
        minDisplayRange = 15 // 湿度：最小15%范围
      } else if (props.legendName.includes('压力')) {
        minDisplayRange = 30 // 压力：最小30Kpa范围
      } else if (props.legendName.includes('红外')) {
        minDisplayRange = 6 // 红外：最小6度范围
      }
      
      // 更稳定的阈值检查
      const currentRange = lastRange.value.max - lastRange.value.min
      const currentCenter = (lastRange.value.min + lastRange.value.max) / 2
      const dataCenter = (result.min + result.max) / 2
      
      const shouldRecalculate = (
        // 数据中心点偏移超过当前范围的25%
        Math.abs(dataCenter - currentCenter) > currentRange * 0.25 ||
        // 数据超出当前显示范围
        result.min < lastRange.value.min || result.max > lastRange.value.max ||
        // 初始化时
        currentRange === 0 ||
        // 数据范围发生显著变化时
        (result.max - result.min) > currentRange * 1.8
      )
      
      if (shouldRecalculate) {
        const dataRange = result.max - result.min
        const dataCenter = (result.min + result.max) / 2
        
        // 确定实际使用的范围（至少为最小显示范围）
        const actualRange = Math.max(dataRange * 1.5, minDisplayRange)
        const halfRange = actualRange / 2
        
        // 以数据中心为基准，创建对称的显示范围
        let minY = dataCenter - halfRange
        let maxY = dataCenter + halfRange
        
        // 确保最小值不小于0（对于物理量传感器）
        if (minY < 0) {
          minY = 0
          maxY = actualRange
        }
        
        // 取整以获得更好的显示效果
        minY = Math.floor(minY)
        maxY = Math.ceil(maxY)
        
        chartRange.value.min = minY
        chartRange.value.max = maxY
        lastRange.value.min = minY
        lastRange.value.max = maxY
        
        // console.log(`${props.legendName} 范围调整: 数据[${result.min.toFixed(1)}-${result.max.toFixed(1)}], 显示[${minY}-${maxY}], 中心: ${dataCenter.toFixed(1)}`)
      }
    } else {
      // 没有数据时使用默认范围
      chartRange.value = { min: 0, max: 100 }
      lastRange.value = { min: 0, max: 100 }
    }
  }

  // 计算是否显示标签（根据屏幕尺寸和数据点数量决定）
  const screenWidth = window.innerWidth
  const isLargeScreen = screenWidth > 1000 // 大屏幕阈值
  const showLabel = (props.isZoomed && allValues.length <= 150) || (!props.isZoomed && isLargeScreen && allValues.length <= 50)
  
  let series: any[] = [];
  if (dataValues.length > 0 && dataValues[0].length > 0 && dataValues[0].some(v => v !== null && v !== undefined)) {
    // 检查是否需要启用large模式（紫外放大模式下超过150个点）
    const shouldUseLargeMode = isUV && props.isZoomed && allValues.length > 280;
    
    series = dataValues.map((arr) => ({
      name: props.legendName,
      animation: false,
      data: arr,
      type: 'line',
      smooth: true,
      // 启用large模式优化大数据量渲染
      large: shouldUseLargeMode,
      largeThreshold: 150,
      lineStyle: {
        color: props.color,
        width: 3
      },
      symbolSize: shouldUseLargeMode ? 1 : 6, // large模式下将标记点设为1，而不是0
      label: {
        show: shouldUseLargeMode ? false : showLabel, // large模式下隐藏标签
        position: 'top',
        color: '#fff',
        fontSize: 10,
        formatter: '{c}'
      },
      itemStyle: {
        color: props.color,
        borderColor: '#fff',
        borderWidth: 1
      }
    }))
  }

  // 性能优化：只更新变化的部分
  const updateOption = {
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(255, 255, 255, 0.9)',
      borderColor: '#1890ff',
      borderWidth: 1,
      textStyle: {
        color: '#333'
      },
      axisPointer: {
        type: 'cross',
        snap: true, // 确保tooltip吸附到最近的数据点
        label: {
          backgroundColor: '#6a7985'
        },
        lineStyle: {
          color: '#ff4d4f',
          width: 1,
          type: 'solid'
        }
      },
      formatter: (params: any[]) => {
        const param = params[0];
        let time = param.name;
        const value = param.value;
        const seriesName = param.seriesName;
        
        // 格式化时间显示，与x轴保持一致
        const date = new Date(time);
        if (!isNaN(date.getTime())) {
          const hours = date.getHours().toString().padStart(2, '0');
          const minutes = date.getMinutes().toString().padStart(2, '0');
          const seconds = date.getSeconds().toString().padStart(2, '0');
          time = `${hours}:${minutes}:${seconds}`;
        }
        
        // console.log('tooltip时间:', time)
        return `
          时间：${time}<br/>
          ${seriesName}：<b>${value}</b>
        `;
      }
    },
    xAxis: {
      data: xAxisValues,
      axisLabel: { 
        show: allValues.length > 0
      }
    },
    yAxis: {
      min: chartRange.value.min,
      max: chartRange.value.max,
      axisLabel: { show: allValues.length > 0 }
    },
    series
  }
  chart.value.setOption(updateOption, { notMerge: false, silent: true });
}

const updateChart = () => {
  // 使用逐帧渲染优化，特别是在紫外放大模式下
  if (isUV && props.isZoomed) {
    // 紫外放大模式：添加高频更新节流控制
    const now = Date.now()
    if (now - lastUpdateTime < MIN_UPDATE_INTERVAL) {
      return // 跳过过于频繁的更新
    }
    lastUpdateTime = now
    
    scheduleFrameUpdate();
  } else {
    performChartUpdate();
  }
}

onMounted(() => {
  // 使用 ResizeObserver 监听容器尺寸变化
  if (chartRef.value) {
    resizeObserver = new ResizeObserver(() => {
      handleChartResize()
    })
    resizeObserver.observe(chartRef.value)
  }
})

onUnmounted(() => {
  if (resizeObserver && chartRef.value) {
    resizeObserver.unobserve(chartRef.value)
    resizeObserver.disconnect()
  }
  // 清理动画帧
  if (frameRequestId) {
    cancelAnimationFrame(frameRequestId)
    frameRequestId = null
  }
  // 清理图表实例
  if (chart.value) {
    chart.value.dispose()
    chart.value = null
  }
  // 重置初始化状态
  isInitialized = false
  baseOption = null
  pendingUpdate = false
})

const handleZoom = () => {
  emit('zoom', props.zoomId)
}

// 重置图表（用于切换模式时）
const resetChart = () => {
  if (chart.value) {
    chart.value.dispose()
    chart.value = null
  }
  isInitialized = false
  baseOption = null
  // 重新初始化
  updateChart()
}

defineExpose({ updateChart, resetChart, resize: handleChartResize })
</script>

<style scoped lang="less">

.chart {
  width: 100%;
  height: 100%;
  flex: 1;
  min-height: 0;
  padding-left: 5px;
  border: 0.008rem solid rgba(14,253,255,0.5);
  position: relative;
  display: flex;
  flex-direction: column;
  .chart-unit {
    color: #ffe066;
    font-size: 13px;
    margin-bottom: 2px;
    margin-left: 2px;
    font-weight: bold;
  }
  .chart-item {
    flex: 1;
    min-height: 0;
    height: 100%;
  }

  h3 {
    font-size: 16px;
    color: #fff;
    height: 50px;
    line-height: 50px;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;

    .title-text {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      min-width: 0; /* Important for flexbox truncation */
    }

    .max-value-display {
      position: absolute;
      left: 50%;
      top: 0;
      transform: translateX(-50%);
      display: flex;
      align-items: center;
      background: linear-gradient(135deg, rgba(14, 253, 255, 0.2), rgba(14, 253, 255, 0.1));
      border: 1px solid rgba(14, 253, 255, 0.5);
      border-radius: 8px;
      padding: 4px 12px;
      margin: 0 15px;
      box-shadow: 0 2px 8px rgba(14, 253, 255, 0.3);
      backdrop-filter: blur(5px);
      flex-shrink: 0;
      
      .max-label {
        color: #0EFDFF;
        font-size: 12px;
        font-weight: 500;
        margin-right: 6px;
      }
      
      .max-value {
        color: #FFE066;
        font-size: 14px;
        font-weight: bold;
        text-shadow: 0 0 4px rgba(255, 224, 102, 0.5);
      }
      
      .max-unit {
        color: #fff;
        font-size: 11px;
        margin-left: 3px;
        opacity: 0.8;
      }
    }

    .icon-container {
      flex-shrink: 0;
      
      .el-icon {
        cursor: pointer;
        z-index: 10;
      }
    }
  }

  .border_bg_leftTop {
    position: absolute;
    left: -0.008rem;
    top: -0.04rem;
    width: 0.37rem;
    height: 0.05rem;
    display: block;
    background: #29292f url("@/assets/images/title_left_bg.png") no-repeat;
    background-size: cover;
  }
}
</style>